package com.goldsprite.infinityworld.entities.randommap;

import com.badlogic.gdx.graphics.*;
import com.badlogic.gdx.graphics.g2d.*;
import com.badlogic.gdx.maps.tiled.*;
import java.util.*;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.maps.MapLayers;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer.Cell;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
import com.badlogic.gdx.maps.tiled.tiles.StaticTiledMapTile;
import com.goldsprite.gdxcore.entities.Renderable;
import com.goldsprite.gdxcore.logs.LogViewerService;
import com.goldsprite.infinityworld.assets.GlobalAssets;
import com.goldsprite.simplexnoise.SimplexNoise2D;
import com.goldsprite.utils.math.Vector2;

public class RandomMapEntity extends Renderable {
	public Vector2 spawnPos = new Vector2().set(10, 10);//区块初始化点
	public float blockSize = 32;//方块渲染大小
	public int blockSplit = 16;//材质切分单位
	public Texture tex;//所有方块源材质
	public CellAssets cellAssets;//方块材质资源
	public TiledMap map;
	public OrthogonalTiledMapRenderer renderer;
	public OrthographicCamera camera;
	public Batch mapBatch;


	public void init(){
		tex = GlobalAssets.getInstance().cellTextures;
		cellAssets = new CellAssets(tex, blockSplit);

		initMap();
	}

	private void initMap(){
		//世界
		{
			Texture tiles = new Texture(Gdx.files.internal(BlockId.cellTexturesPath));
			TextureRegion[][] splitTiles = TextureRegion.split(tiles, BlockId.regionSplit, BlockId.regionSplit);

			map = new TiledMap();
			MapLayers layers = map.getLayers();
			int chunkGridUnitX = 64/4, chunkGridUnitY = 64/4;
			int chunkCountX = 16/2, chunkCountY = 16/2;
			int totalBlockCountX = chunkGridUnitX * chunkCountX;
			int totalBlockCountY = chunkGridUnitY * chunkCountY;
			int layerCount = 2;
			for (int l = 0; l < layerCount; l++) {
				TiledMapTileLayer layer = new TiledMapTileLayer(totalBlockCountX, totalBlockCountY, BlockId.regionSplit, BlockId.regionSplit);
				//layer.setOffsetX(100);
				//layer.setParallaxX(0.9f);
				//layer.setParallaxY(0.9f);

				int startX = 1000, startY = 2000;
				for (int y = 0; y < totalBlockCountY; y++) {
					for (int x = 0; x < totalBlockCountX; x++) {
						//随机id
						BlockId blockId = getRanBlock(startX+x, startY+y, l);
						TextureRegion region = splitTiles[blockId.y][blockId.x];
						Cell cell = new Cell();
						cell.setTile(new StaticTiledMapTile(region));

						layer.setCell(x, y, cell);
					}
				}

				layers.add(layer);
			}
			LogViewerService.log("map: "+map);
			LogViewerService.log("layers: "+layers+"count: "+layers.size());
		}

		//渲染器
		mapBatch = new SpriteBatch();
		renderer = new OrthogonalTiledMapRenderer(map, mapBatch);
	}

	@Override
	public void render(Batch batch, float delta) {
		OrthographicCamera targetCam = world.worldCam;
		renderer.setView(targetCam);
		renderer.render();
	}

	private int minHigh = -64, maxHigh = 64;
	private BlockId getRanBlock(int x, int y, int type){
		double noise = SimplexNoise2D.getNorNoise(x, y, 0.02, 5, 0.45);
		double height = mapNoiseToHeight(noise, minHigh, maxHigh);
		BlockId blockId = getBlockIdForHeight(height);

		//生成obj(树等)
		BlockId objId = BlockId.Air;
		//ran决定出现树的覆盖率
		float ran = new Random((long)(noise*1_000_000)).nextFloat();
		//草地树
		if(height>40+off){
			if(ran > 0.5f){
				if(ran < 0.65f) objId = BlockId.Tree;
				else objId = BlockId.Tree2;
			}
		}
		//沙滩树
		if(height>28+off+1 && height<34+off){
			if(ran > 0.8f)objId = BlockId.BeachTree;
		}

		return type == 0 ?blockId :objId;
	}

	////旧版代码
	public int off = -22;//越小目标高度面积越大
    // 高度映射表：每个高度范围对应一个BlockId
    public TreeMap<Integer, BlockId> heightMap = new TreeMap<Integer, BlockId>(){{
			//put(64+off, BlockId.Air);
			put(40+off, BlockId.Grass);
			put(38+off, BlockId.Grass2);
			put(34+off, BlockId.Sand);
			put(28+off, BlockId.Water);
			put(24+off, BlockId.Water2);
			put(18+off, BlockId.Water3);
			put(10+off, BlockId.Water4);
		}};
    public TreeMap<Integer, BlockId> obj_heightMap = new TreeMap<Integer, BlockId>(){{
			//put(64+off, BlockId.Air);
			put(45+off, BlockId.Tree);
			put(40+off, BlockId.Air);
		}};

	// 将噪声值映射到指定的高度区间, 接收值区间: 0 ~ 1
    private double mapNoiseToHeight(double noiseValue, int minHeight, int maxHeight) {
        return minHeight + noiseValue * (maxHeight - minHeight);
    }

    // 根据高度值查找对应的BlockId
    private BlockId getBlockIdForHeight(double height) {
		Integer key = heightMap.ceilingKey((int) height);  // 向上对齐到最近的高度
		if (key == null) key = heightMap.lastKey();
		return heightMap.get(key);
	}
}
